describe('tests for jQuery.override.js',function(){

	it("override a method and call $super()", function() {
		    
		// define the properties of a person
		var Person = {
		  initialize: function(name) {
		    this.name = name;
		  },
		  say: function(message) {
		    return "" + this.name + ': ' + message;
		  },
		  shout: function(message) {
		    return this.say(message) + "!";
		  }
		};

		// define the properties of a pirate (he is like a person)
		var Pirate = jQuery.extend({}, Person);
		// redefine the speech of the pirate
		jQuery.override(Pirate, {
		  say: function($super, message) {
		    return $super(message) + ', yarr';
		  }
		});

		// create and initialize the pirate "Long John"
		var john = jQuery.extend({}, Pirate);
		john.initialize('Long John');

		// let the pirate speak
		expect(john.shout('ahoy matey')).toBe("Long John: ahoy matey, yarr!");
		
	});

	it("override a method and do not call $super()", function() {
	    
		// define the properties of a person
		var Person = {
		  initialize: function(name) {
		    this.name = name;
		  },
		  say: function(message) {
		    return "" + this.name + ': ' + message;
		  },
		  shout: function(message) {
		    return this.say(message) + "!";
		  }
		};

		// define the properties of a pirate (he is like a person)
		var Pirate = jQuery.extend({}, Person);
		// redefine the speech of the pirate
		jQuery.override(Pirate, {
		  say: function($super, message) {
		    return  'Pirate: ' + message + ' *grrr*';
		  }
		});

		// create and initialize the pirate "Long John"
		var john = jQuery.extend({}, Pirate);
		john.initialize('Long John');

		// let the pirate speak
		expect(john.shout('ahoy matey')).toBe("Pirate: ahoy matey *grrr*!");
		
	});

	it("override a method without a method parameter and call $super()", function() {
	    
		// define the properties of a person
		var Person = {
		  initialize: function(name) {
		    this.name = name;
		  },
		  say: function() {
		    return "" + this.name + ": Hi!";
		  },
		  shout: function(message) {
		    return this.say(message) + "!";
		  }
		};

		// define the properties of a pirate (he is like a person)
		var Pirate = jQuery.extend({}, Person);
		// redefine the speech of the pirate
		jQuery.override(Pirate, {
		  say: function($super) {
		    return  $super() + ' *grrr*';
		  }
		});

		// create and initialize the pirate "Long John"
		var john = jQuery.extend({}, Pirate);
		john.initialize('Long John');

		// let the pirate speak
		expect(john.shout()).toBe("Long John: Hi! *grrr*!");
		
	});

	it("override a method without a method parameter and do not call $super()", function() {
	    
		// define the properties of a person
		var Person = {
		  initialize: function(name) {
		    this.name = name;
		  },
		  say: function() {
		    return "" + this.name + " Hi!";
		  },
		  shout: function(message) {
		    return this.say(message) + "!";
		  }
		};

		// define the properties of a pirate (he is like a person)
		var Pirate = jQuery.extend({}, Person);
		// redefine the speech of the pirate
		jQuery.override(Pirate, {
		  say: function($super) {
		    return  'Pirate: *grrr*';
		  }
		});

		// create and initialize the pirate "Long John"
		var john = jQuery.extend({}, Pirate);
		john.initialize('Long John');

		// let the pirate speak
		expect(john.shout()).toBe("Pirate: *grrr*!");
		
	});

	it("override a method without three method parameters and call $super()", function() {
	    
		// define the properties of a person
		var Person = {
		  say: function(word1, word2, word3) {
		    return word1 + " " + word2 + " " + word3;
		  },
		  shout: function() {
		    return this.say("Hi", "mate", "how are you") + "!";
		  }
		};

		// define the properties of a pirate (he is like a person)
		var Pirate = jQuery.extend({}, Person);
		// redefine the speech of the pirate
		jQuery.override(Pirate, {
		  say: function($super, param1, param2, param3) {
		    return  $super(param1 + "ey", param2 + "eyy", param3 + "eyyy");
		  }
		});

		// create and initialize the pirate "Long John"
		var john = jQuery.extend({}, Pirate);

		// let the pirate speak
		expect(john.shout()).toBe("Hiey mateeyy how are youeyyy!");
		
	});
	
	it("override a method without a return value and call $super()", function() {

		// define a horizontal slider with a position
		var mySlider = {

			position : 0,

			render : function(newPosition) {
				this.position = newPosition;
				// ... do the rendering now ...
			},

			mouseover : function(mouseEvent) {
				this.render(mouseEvent.pageX);
			}
		};

		// enhance the widget by redefining the method render()
		jQuery.override(mySlider, {

			// the slider shall be positioned ten pixels to the right of the
			// mouse pointer
			render : function($super, newPosition) {
				// you should use $super without the keyword "this"
				$super(newPosition + 10);
			}

		});

		// send a mouse event to the slider
		mySlider.mouseover({
			pageX : 400,
			pageY : 500
		});
		expect(mySlider.position).toBe(410);

	});

	it("override three methods at the same time", function() {

		// define the properties of a person
		var Person = {
		  initialize: function(name) {
		    this.name = name;
		  },
		  say: function(message) {
		    return "" + this.name + ': ' + message;
		  },
		  shout: function(message) {
		    return this.say(message) + "!";
		  },
		  wonder: function(message) {
			return this.shout(message) + "?";
		  }
		};

		// define the properties of a pirate (he is like a person)
		var Pirate = jQuery.extend({}, Person);
		// redefine the speech of the pirate
		jQuery.override(Pirate, {
		  wonder: function($super, message) {
			return $super(message) + " :-o";
		  },
		  say: function($super, message) {
		    return  $super(message) + ' , yarr';
		  },
		  shout: function($super, message) {
			return $super(message) + "!!!";
		  }
		});

		// create and initialize the pirate "Long John"
		var john = jQuery.extend({}, Pirate);
		john.initialize('Long John');

		// let the pirate speak
		expect(john.wonder('really')).toBe("Long John: really , yarr!!!!? :-o");
		
	});

	it("missing or undefined arguments", function() {
	    
		var thrown = null;
		try {
			jQuery.override({}, null);
		} catch(e) {
			thrown = e;
		}
		expect(thrown).toBe("missing arguments: [object Object], null");

		var thrown = null;
		try {
			jQuery.override(null, {});
		} catch(e) {
			thrown = e;
		}
		expect(thrown).toBe("missing arguments: null, [object Object]");

		var thrown = null;
		try {
			jQuery.override({});
		} catch(e) {
			thrown = e;
		}
		expect(thrown).toBe("missing arguments: [object Object], undefined");

	});
	
	it("override a method but the target does not have a method with the same name", function() {
	    
		var myObject = {
		  doSomething: function(message) { }
		};

		var thrown = null;
		try {
			jQuery.override(myObject, {
				doSomethingElse: function($super, message) { }
			});
		} catch(e) {
			thrown = e;
		}
		expect(thrown).toBe("property is missing or not of type 'function':" +
				" doSomethingElse, undefined, function ($super, message) {\n}");
	});

	it("override a method but the target does have a property with the same name", function() {
	    
		var myObject = {
		  doSomething: { }
		};

		var thrown = null;
		try {
			jQuery.override(myObject, {
				doSomething: function($super, message) { }
			});
		} catch(e) {
			thrown = e;
		}
		expect(thrown).toBe("property is missing or not of type 'function':" +
				" doSomething, [object Object], function ($super, message) {\n}");
	});

	it("override with a property instead of a method (this is not allowed)", function() {
	    
		var myObject = {
			doSomething: function(message) { }
		};

		var thrown = null;
		try {
			jQuery.override(myObject, {
				doSomething: { }
			});
		} catch(e) {
			thrown = e;
		}
		expect(thrown).toBe("property is missing or not of type 'function':" +
				" doSomething, function (message) {\n}, [object Object]");
	});

	it("transfers properties from the original method and the redefined method to the new method", function() {
	    
		// define the properties of the original object
		var myObject = {
		  m: function() {
		    return "m";
		  },
		  n: function(x, y) {
			    return "n";
			  }
		};
		myObject.m["m1"] = "It's an m1.";
		myObject.m["m2"] = "It's an m2.";
		myObject.n["n1"] = "It's an n1.";
		myObject.n["n2"] = "It's an n2.";

		var redefinedMethods = {
		  m: function($super) {
		    return $super();
		  },
		  n: function($super, x, y) {
			    return $super(x,y);
			  }
		};

		redefinedMethods.m["m1"] = "It's a new m1.";
		redefinedMethods.m["m3"] = "It's a new m3.";
		redefinedMethods.n["n1"] = "It's a new n1.";
		redefinedMethods.n["n3"] = "It's a new n3.";

		// override the methods
		jQuery.override(myObject, redefinedMethods);

		expect(myObject.m["m1"]).toBe("It's a new m1.");
		expect(myObject.m["m2"]).toBe("It's an m2.");
		expect(myObject.m["m3"]).toBe("It's a new m3.");
		expect(myObject.n["n1"]).toBe("It's a new n1.");
		expect(myObject.n["n2"]).toBe("It's an n2.");
		expect(myObject.n["n3"]).toBe("It's a new n3.");
		
	});

});
